import CryptoJS from 'crypto-js'

// 十六位十六进制数作为密钥
const SECRET_KEY = CryptoJS.enc.Utf8.parse('3333e6e143439161')
// 十六位十六进制数作为密钥偏移量
const SECRET_IV = CryptoJS.enc.Utf8.parse('e3bbe7e3ba84431a')

// 类型 window.localStorage,window.sessionStorage,
const config = {
  type: 'localStorage', // 本地存储类型 sessionStorage
  isEncrypt: true // 默认加密 为了调试方便, 开发过程中可以不加密
}

// 判断是否支持 Storage
export const isSupportStorage = () => {
  return typeof Storage !== 'undefined' ? true : false
}

// 设置 setStorage
export const setStorage = (key: any, value: any) => {
  if (value === '' || value === null || value === undefined) {
    value = null
  }

  const encryptString = config.isEncrypt ? encrypt(value) : value

  window[config.type].setItem(key, encryptString)
}

// 获取 getStorage
export const getStorage = (key: any) => {
  // key 不存在判断
  if (
    !window[config.type].getItem(key) ||
    JSON.stringify(window[config.type].getItem(key)) === 'null'
  ) {
    return null
  } else {
    return config.isEncrypt
      ? decrypt(window[config.type].getItem(key))
      : window[config.type].getItem(key)
  }
}

// 删除 removeStorage
export const removeStorage = (key: any) => {
  window[config.type].removeItem(key)
}

// 清空 clearStorage
export const clearStorage = () => {
  window[config.type].clear()
}

/**
 * 加密方法
 * @param data
 * @returns {string}
 */
const encrypt = (data: any): string => {
  if (typeof data === 'object') {
    try {
      data = JSON.stringify(data)
    } catch (error) {
      console.log('encrypt error:', error)
    }
  }
  const dataHex = CryptoJS.enc.Utf8.parse(data)
  const encrypted = CryptoJS.AES.encrypt(dataHex, SECRET_KEY, {
    iv: SECRET_IV,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  })
  return encrypted.ciphertext.toString()
}

/**
 * 解密方法
 * @param data
 * @returns {string}
 */
const decrypt = (data: string): string => {
  const encryptedHexStr = CryptoJS.enc.Hex.parse(data)
  const str = CryptoJS.enc.Base64.stringify(encryptedHexStr)
  const decrypt = CryptoJS.AES.decrypt(str, SECRET_KEY, {
    iv: SECRET_IV,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  })
  const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
  return decryptedStr.toString()
}
